package com.uniflow.service;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.uniflow.entity.AuditLogs;
import com.uniflow.mapper.AuditLogMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * 审计日志服务层
 * 
 * @author uniflow
 * @since 1.0.0
 */
@Service
public class AuditLogService {
    
    @Autowired
    private AuditLogMapper auditLogMapper;
    
    /**
     * 分页查询审计日志
     */
    public IPage<AuditLogs> getAuditLogPage(int pageNum, int pageSize, String userId, String username, String operationType,
                                            String resourceType, String resourceId, String operationResult, String requestIp,
                                            LocalDateTime startDate, LocalDateTime endDate, String keyword) {
        Page<AuditLogs> page = new Page<>(pageNum, pageSize);
        return auditLogMapper.selectAuditLogPage(page, userId, username, operationType, resourceType, resourceId, 
                                                operationResult, requestIp, startDate, endDate, keyword);
    }
    
    /**
     * 根据ID查询审计日志
     */
    public AuditLogs getAuditLogById(String id) {
        return auditLogMapper.selectById(id);
    }
    
    /**
     * 根据用户ID查询审计日志
     */
    public List<AuditLogs> getAuditLogsByUserId(String userId, Integer limit) {
        return auditLogMapper.selectByUserId(userId, limit);
    }
    
    /**
     * 根据操作类型查询审计日志
     */
    public List<AuditLogs> getAuditLogsByOperationType(String operationType, Integer limit) {
        return auditLogMapper.selectByOperationType(operationType, limit);
    }
    
    /**
     * 根据资源类型查询审计日志
     */
    public List<AuditLogs> getAuditLogsByResourceType(String resourceType, Integer limit) {
        return auditLogMapper.selectByResourceType(resourceType, limit);
    }
    
    /**
     * 根据资源ID查询审计日志
     */
    public List<AuditLogs> getAuditLogsByResourceId(String resourceType, String resourceId) {
        return auditLogMapper.selectByResourceId(resourceType, resourceId);
    }
    
    /**
     * 根据操作结果查询审计日志
     */
    public List<AuditLogs> getAuditLogsByOperationResult(String operationResult, Integer limit) {
        return auditLogMapper.selectByOperationResult(operationResult, limit);
    }
    
    /**
     * 根据IP地址查询审计日志
     */
    public List<AuditLogs> getAuditLogsByRequestIp(String requestIp, Integer limit) {
        return auditLogMapper.selectByRequestIp(requestIp, limit);
    }
    
    /**
     * 查询指定时间范围内的审计日志
     */
    public List<AuditLogs> getAuditLogsByDateRange(LocalDateTime startDate, LocalDateTime endDate) {
        return auditLogMapper.selectByDateRange(startDate, endDate);
    }
    
    /**
     * 创建审计日志
     */
    @Transactional
    public AuditLogs createAuditLog(AuditLogs auditLog) {
        // 生成ID
        auditLog.setId(UUID.randomUUID().toString().replace("-", ""));
        
        // 设置操作时间
        if (auditLog.getOperationTime() == null) {
            auditLog.setOperationTime(LocalDateTime.now());
        }
        
        auditLogMapper.insert(auditLog);
        return auditLog;
    }
    
    /**
     * 批量创建审计日志
     */
    @Transactional
    public void createAuditLogs(List<AuditLogs> auditLogs) {
        LocalDateTime now = LocalDateTime.now();
        for (AuditLogs auditLog : auditLogs) {
            auditLog.setId(UUID.randomUUID().toString().replace("-", ""));
            if (auditLog.getOperationTime() == null) {
                auditLog.setOperationTime(now);
            }
        }
        auditLogMapper.insertBatch(auditLogs);
    }
    
    /**
     * 记录用户操作日志
     */
    @Transactional
    public void logUserOperation(String userId, String username, String operationType, String resourceType, 
                                String resourceId, String resourceName, String operationDesc, 
                                String requestIp, String userAgent, String requestUrl, String requestMethod,
                                String requestParams, String oldData, String newData, 
                                String operationResult, String errorMessage) {
        AuditLogs auditLog = new AuditLogs();
        auditLog.setUserId(userId);
        auditLog.setUsername(username);
        auditLog.setOperationType(operationType);
        auditLog.setResourceType(resourceType);
        auditLog.setResourceId(resourceId);
        auditLog.setResourceName(resourceName);
        auditLog.setOperationDesc(operationDesc);
        auditLog.setRequestIp(requestIp);
        auditLog.setUserAgent(userAgent);
        auditLog.setRequestUrl(requestUrl);
        auditLog.setRequestMethod(requestMethod);
        auditLog.setRequestParams(requestParams);
        auditLog.setOldData(oldData);
        auditLog.setNewData(newData);
        auditLog.setOperationResult(operationResult);
        auditLog.setErrorMessage(errorMessage);
        
        createAuditLog(auditLog);
    }
    
    /**
     * 记录登录日志
     */
    @Transactional
    public void logLogin(String userId, String username, String requestIp, String userAgent, boolean success, String errorMessage) {
        logUserOperation(userId, username, AuditLogs.OperationType.LOGIN, AuditLogs.ResourceType.USER,
                        userId, username, success ? "用户登录成功" : "用户登录失败", 
                        requestIp, userAgent, "/api/v1/auth/login", "POST", null, null, null,
                        success ? AuditLogs.OperationResult.SUCCESS : AuditLogs.OperationResult.FAILURE, errorMessage);
    }
    
    /**
     * 记录登出日志
     */
    @Transactional
    public void logLogout(String userId, String username, String requestIp, String userAgent) {
        logUserOperation(userId, username, AuditLogs.OperationType.LOGOUT, AuditLogs.ResourceType.USER,
                        userId, username, "用户登出", 
                        requestIp, userAgent, "/api/v1/auth/logout", "POST", null, null, null,
                        AuditLogs.OperationResult.SUCCESS, null);
    }
    
    /**
     * 记录数据创建日志
     */
    @Transactional
    public void logCreate(String userId, String username, String resourceType, String resourceId, String resourceName,
                         String newData, String requestIp, String userAgent, String requestUrl) {
        logUserOperation(userId, username, AuditLogs.OperationType.CREATE, resourceType,
                        resourceId, resourceName, "创建" + resourceType, 
                        requestIp, userAgent, requestUrl, "POST", null, null, newData,
                        AuditLogs.OperationResult.SUCCESS, null);
    }
    
    /**
     * 记录数据更新日志
     */
    @Transactional
    public void logUpdate(String userId, String username, String resourceType, String resourceId, String resourceName,
                         String oldData, String newData, String requestIp, String userAgent, String requestUrl) {
        logUserOperation(userId, username, AuditLogs.OperationType.UPDATE, resourceType,
                        resourceId, resourceName, "更新" + resourceType, 
                        requestIp, userAgent, requestUrl, "PUT", null, oldData, newData,
                        AuditLogs.OperationResult.SUCCESS, null);
    }
    
    /**
     * 记录数据删除日志
     */
    @Transactional
    public void logDelete(String userId, String username, String resourceType, String resourceId, String resourceName,
                         String oldData, String requestIp, String userAgent, String requestUrl) {
        logUserOperation(userId, username, AuditLogs.OperationType.DELETE, resourceType,
                        resourceId, resourceName, "删除" + resourceType, 
                        requestIp, userAgent, requestUrl, "DELETE", null, oldData, null,
                        AuditLogs.OperationResult.SUCCESS, null);
    }
    
    /**
     * 查询今日审计日志统计
     */
    public Map<String, Object> getTodayStats() {
        return auditLogMapper.selectTodayStats();
    }
    
    /**
     * 查询审计日志统计信息
     */
    public Map<String, Object> getAuditStats(LocalDateTime startDate, LocalDateTime endDate) {
        return auditLogMapper.selectAuditStats(startDate, endDate);
    }
    
    /**
     * 查询操作类型统计
     */
    public List<Map<String, Object>> getOperationTypeStats(LocalDateTime startDate, LocalDateTime endDate) {
        return auditLogMapper.selectOperationTypeStats(startDate, endDate);
    }
    
    /**
     * 查询资源类型统计
     */
    public List<Map<String, Object>> getResourceTypeStats(LocalDateTime startDate, LocalDateTime endDate) {
        return auditLogMapper.selectResourceTypeStats(startDate, endDate);
    }
    
    /**
     * 查询用户操作统计
     */
    public List<Map<String, Object>> getUserOperationStats(LocalDateTime startDate, LocalDateTime endDate, Integer limit) {
        return auditLogMapper.selectUserOperationStats(startDate, endDate, limit);
    }
    
    /**
     * 查询操作结果统计
     */
    public List<Map<String, Object>> getOperationResultStats(LocalDateTime startDate, LocalDateTime endDate) {
        return auditLogMapper.selectOperationResultStats(startDate, endDate);
    }
    
    /**
     * 查询IP访问统计
     */
    public List<Map<String, Object>> getIpAccessStats(LocalDateTime startDate, LocalDateTime endDate, Integer limit) {
        return auditLogMapper.selectIpAccessStats(startDate, endDate, limit);
    }
    
    /**
     * 查询时段访问统计
     */
    public List<Map<String, Object>> getHourlyAccessStats(LocalDateTime startDate, LocalDateTime endDate) {
        return auditLogMapper.selectHourlyAccessStats(startDate, endDate);
    }
    
    /**
     * 查询失败操作统计
     */
    public List<AuditLogs> getFailedOperations(LocalDateTime startDate, LocalDateTime endDate, Integer limit) {
        return auditLogMapper.selectFailedOperations(startDate, endDate, limit);
    }
    
    /**
     * 查询高风险操作
     */
    public List<AuditLogs> getHighRiskOperations(LocalDateTime startDate, LocalDateTime endDate, Integer limit) {
        return auditLogMapper.selectHighRiskOperations(startDate, endDate, limit);
    }
    
    /**
     * 查询异常IP访问
     */
    public List<Map<String, Object>> getAbnormalIpAccess(LocalDateTime startDate, LocalDateTime endDate) {
        return auditLogMapper.selectAbnormalIpAccess(startDate, endDate);
    }
    
    /**
     * 查询频繁操作用户
     */
    public List<Map<String, Object>> getFrequentUsers(LocalDateTime startDate, LocalDateTime endDate, Integer limit) {
        return auditLogMapper.selectFrequentUsers(startDate, endDate, limit);
    }
    
    /**
     * 查询资源访问热度
     */
    public List<Map<String, Object>> getResourceAccessHeat(String resourceType, LocalDateTime startDate, LocalDateTime endDate, Integer limit) {
        return auditLogMapper.selectResourceAccessHeat(resourceType, startDate, endDate, limit);
    }
    
    /**
     * 查询操作趋势
     */
    public List<Map<String, Object>> getOperationTrend(String operationType, LocalDateTime startDate, LocalDateTime endDate, String groupBy) {
        return auditLogMapper.selectOperationTrend(operationType, startDate, endDate, groupBy);
    }
    
    /**
     * 查询安全事件
     */
    public List<AuditLogs> getSecurityEvents(LocalDateTime startDate, LocalDateTime endDate) {
        return auditLogMapper.selectSecurityEvents(startDate, endDate);
    }
    
    /**
     * 查询数据变更记录
     */
    public List<AuditLogs> getDataChanges(String resourceType, String resourceId) {
        return auditLogMapper.selectDataChanges(resourceType, resourceId);
    }
    
    /**
     * 查询用户登录记录
     */
    public List<AuditLogs> getUserLoginLogs(String userId, LocalDateTime startDate, LocalDateTime endDate) {
        return auditLogMapper.selectUserLoginLogs(userId, startDate, endDate);
    }
    
    /**
     * 查询权限变更记录
     */
    public List<AuditLogs> getPermissionChanges(String userId, LocalDateTime startDate, LocalDateTime endDate) {
        return auditLogMapper.selectPermissionChanges(userId, startDate, endDate);
    }
    
    /**
     * 查询系统配置变更记录
     */
    public List<AuditLogs> getConfigChanges(LocalDateTime startDate, LocalDateTime endDate) {
        return auditLogMapper.selectConfigChanges(startDate, endDate);
    }
    
    /**
     * 清理过期审计日志
     */
    @Transactional
    public int cleanupExpiredLogs(LocalDateTime expireDate) {
        return auditLogMapper.deleteExpiredLogs(expireDate);
    }
    
    /**
     * 归档审计日志
     */
    @Transactional
    public int archiveLogs(LocalDateTime archiveDate) {
        return auditLogMapper.archiveLogs(archiveDate);
    }
    
    /**
     * 查询审计日志总数
     */
    public Long getTotalCount() {
        return auditLogMapper.selectTotalCount();
    }
    
    /**
     * 查询指定时间范围内的日志数量
     */
    public Long getCountByDateRange(LocalDateTime startDate, LocalDateTime endDate) {
        return auditLogMapper.selectCountByDateRange(startDate, endDate);
    }
    
    /**
     * 查询增量审计日志
     */
    public List<AuditLogs> getIncrementalLogs(String lastLogId, Integer limit) {
        return auditLogMapper.selectIncrementalLogs(lastLogId, limit);
    }
    
    /**
     * 查询审计日志详情
     */
    public AuditLogs getAuditLogWithDetails(String id) {
        return auditLogMapper.selectWithDetails(id);
    }
    
    /**
     * 查询相关审计日志
     */
    public List<AuditLogs> getRelatedLogs(String resourceType, String resourceId, LocalDateTime operationTime, Integer timeRange) {
        return auditLogMapper.selectRelatedLogs(resourceType, resourceId, operationTime, timeRange);
    }
    
    /**
     * 查询审计日志链路
     */
    public List<AuditLogs> getLogChain(String traceId) {
        return auditLogMapper.selectLogChain(traceId);
    }
    
    /**
     * 查询合规性报告数据
     */
    public List<Map<String, Object>> getComplianceReportData(LocalDateTime startDate, LocalDateTime endDate, String reportType) {
        return auditLogMapper.selectComplianceReportData(startDate, endDate, reportType);
    }
    
    /**
     * 定时清理过期日志
     */
    @Transactional
    public void scheduledCleanup() {
        // 清理90天前的日志
        LocalDateTime expireDate = LocalDateTime.now().minusDays(90);
        int deletedCount = cleanupExpiredLogs(expireDate);
        
        // 记录清理日志
        if (deletedCount > 0) {
            logUserOperation("system", "系统", AuditLogs.OperationType.DELETE, "AUDIT_LOG",
                           null, "审计日志", "定时清理过期审计日志，删除" + deletedCount + "条记录", 
                           "127.0.0.1", "System", "/system/cleanup", "POST", null, null, null,
                           AuditLogs.OperationResult.SUCCESS, null);
        }
    }
}